//
// Created by ct on 2020/10/10.
//
#include "server.h"
#include <csignal>
#include <utility>
namespace http {
    namespace server {
        server::server(const std::string &address, const std::string &port,
                       const std::string &doc_root)
                : io_context_(1),
                  signals_(io_context_),
                  acceptor_(io_context_),
                  connection_manager_(),
                  request_handler_(doc_root) {
            //注册以处理指示服务器何时退出的信号。
            //在一个程序中多次注册同一信号是安全的，
            //如果指定信号的所有注册都是通过Asio完成的。
            signals_.add(SIGINT);
            signals_.add(SIGTERM);
#if defined(SIGQUIT)
            signals_.add(SIGQUIT);
#endif // defined(SIGQUIT)

            do_await_stop();

            // 打开acceptor并选择重用该地址（即SO_REUSEADDR）。
            boost::asio::ip::tcp::resolver resolver(io_context_);
            boost::asio::ip::tcp::endpoint endpoint =
                    *resolver.resolve(address, port).begin();
            acceptor_.open(endpoint.protocol());
            acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
            acceptor_.bind(endpoint);
            acceptor_.listen();

            do_accept();
        }

        void server::run() {
            // The io_context::run() call will block until all asynchronous operations
            // have finished. While the server is running, there is always at least one
            // asynchronous operation outstanding: the asynchronous accept call waiting
            // for new incoming connections.
            io_context_.run();
        }

        void server::do_accept() {
            acceptor_.async_accept(
                    [this](boost::system::error_code ec, boost::asio::ip::tcp::socket socket) {
                        // Check whether the server was stopped by a signal before this
                        // completion handler had a chance to run.
                        if (!acceptor_.is_open()) {
                            return;
                        }

                        if (!ec) {
                            connection_manager_.start(std::make_shared<connection>(
                                    std::move(socket), connection_manager_, request_handler_));
                        }

                        do_accept();
                    });
        }

        void server::do_await_stop() {
            signals_.async_wait(
                    [this](boost::system::error_code /*ec*/, int /*signo*/) {
                        //通过取消所有未完成的异步操作来停止服务器
                        //操作。一旦所有操作都完成io\U context:：run（）
                        //将退出调用。
                        acceptor_.close();
                        connection_manager_.stop_all();
                    });
        }
    } // namespace server
} // namespace http